﻿/////////////////////////////////////////////////////////////////
//
// Silverlight 5: 3D Physics using Balder and Jiglibx
// by Andy Beaulieu - http://www.andybeaulieu.com
//
// LICENSE: This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ANY 
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS
// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
/////////////////////////////////////////////////////////////////
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Balder.Objects.Geometries;
using Microsoft.Xna.Framework;
using JigLibX.Physics;
using JigLibX.Collision;
using jlxg = JigLibX.Geometry;
using JigLibX.Geometry;

namespace Spritehand.Physics3D
{
    public class PhysicsBox : Balder.Objects.Geometries.Box, IPhysicsObject
    {
        PhysicsSystem _world;

        public PhysicsBox()
        {

        }

        public PhysicsBox(PhysicsSystem world, Balder.Math.Coordinate dimension, Balder.Math.Matrix orientation, Balder.Math.Coordinate position)
        {
            this.Dimension = dimension;
            this.Position = position;
            this.World = orientation;
            InitPhysics(_world);
        }

        private Body _physicsBody;
        public Body PhysicsBody()
        {
            return _physicsBody;
        }

        private CollisionSkin _skin;
        public CollisionSkin Skin
        {
            get
            {
                return _skin;
            }
        }

        public bool Immovable
        {
            get
            {
                return _physicsBody.Immovable;
            }
            set
            {
                _physicsBody.Immovable = value;
            }
        }

        public void InitPhysics(PhysicsSystem world)
        {
            _world = world;

            _physicsBody = new Body();

            _skin = new CollisionSkin(_physicsBody);
            _physicsBody.CollisionSkin = _skin;

            jlxg.Box box = new jlxg.Box(Vector3.Zero, Microsoft.Xna.Framework.Matrix.Identity, Utils.VectorBalderToXna(this.Dimension));
            _skin.AddPrimitive(box, new MaterialProperties(0.1f, 0.4f, 0.9f));


            Vector3 com = SetMass(1.0f);

            _physicsBody.MoveTo(Utils.VectorBalderToXna(this.Position), Microsoft.Xna.Framework.Matrix.Identity);
            _skin.ApplyLocalTransform(new JigLibX.Math.Transform(-com, Microsoft.Xna.Framework.Matrix.Identity));
            _physicsBody.EnableBody();

        }

        public void Draw()
        {

            if (_skin == null)
                return;

            this.Position = Utils.VectorXnaToBalder(_skin.NewPosition);

            Microsoft.Xna.Framework.Matrix matrixSrc = _physicsBody.CollisionSkin.GetPrimitiveLocal(0).Transform.Orientation * _physicsBody.Orientation;

            Balder.Math.Matrix matrix = Utils.MatrixXnaToBalder(matrixSrc);

            this.World = matrix;

        }

        private Vector3 SetMass(float mass)
        {
            PrimitiveProperties primitiveProperties = new PrimitiveProperties(
                PrimitiveProperties.MassDistributionEnum.Solid,
                PrimitiveProperties.MassTypeEnum.Mass, mass);

            float junk;
            Vector3 com;
            Microsoft.Xna.Framework.Matrix it;
            Microsoft.Xna.Framework.Matrix itCoM;

            Skin.GetMassProperties(primitiveProperties, out junk, out com, out it, out itCoM);

            _physicsBody.BodyInertia = itCoM;
            _physicsBody.Mass = junk;

            return com;
        }

    }
}
